/*
 * MIT License
 *
 * Copyright (c) 2020 wen.gu <454727014@qq.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/***************************************************************************
 * Name: data_types.h
 *
 * Purpose: define common data type for skeleton and proxy base implmentation
 *
 * Developer:
 *   wen.gu , 2020-04-21
 *
 * TODO:
 *
 ***************************************************************************/

#ifndef __ARA_COM_DATA_TYPES_H__
#define __ARA_COM_DATA_TYPES_H__
/******************************************************************************
 **    INCLUDES
 ******************************************************************************/
#include <sstream>
#include <functional>
#include <memory>

#include "ara/core/string_view.h"
#include "ara/core/string.h"
#include "ara/core/vector.h"
/******************************************************************************
 **    MACROS
 ******************************************************************************/


/******************************************************************************
 **    TYPE DEFINITIONS
 ******************************************************************************/
namespace ara
{
namespace com
{
/** Subscription State */
enum class SubscriptionState : uint8_t
{
    kSubscribed,
    kNotSubscribed,
    kSubscriptionPending
};

/** Method Call Processing Mode */
enum class MethodCallProcessingMode : uint8_t
{
    kPoll,
    kEvent,
    kEventSingleThread
};
/******************************************************************************
 **    CLASSES/FUNCTIONS DEFINITIONS
 ******************************************************************************/
class ServiceIdentifierType
{
public:
    ServiceIdentifierType() = default;
    ServiceIdentifierType(ara::core::StringView sv)
        :mSrvId(sv)
    {
        /** todo something */
    }

    ServiceIdentifierType(const ara::core::String& sv)
        :mSrvId(sv)
    {
        /** todo something */
    }
    //virtual ~ServiceIdentifierType() = default;
public:
    bool operator==(const ServiceIdentifierType& other) const
    {
        return mSrvId == other.mSrvId;
    }

    bool operator<(const ServiceIdentifierType& other) const
    {
        return mSrvId < other.mSrvId;
    }

    ServiceIdentifierType& operator=(const ServiceIdentifierType& other)
    {
        mSrvId = other.mSrvId;
        return *this;
    }

    ara::core::StringView ToString() const { return mSrvId; }
private:
    ara::core::String mSrvId;
};

class ServiceVersionType 
{
public:
    ServiceVersionType()
        :ServiceVersionType(0, 0)
    {
       /** todo something */
    }

    ServiceVersionType(uint8_t versionMajor, int8_t versionMinor)
        :mMajor(versionMajor),
        mMinor(versionMinor)
    {
        std::stringstream ss;
        ss <<versionMajor << "." << versionMinor;

        mVersion = ss.str();
        /** todo something */
    }

    //virtual ~ServiceVersionType() = default;
public:

    bool operator==(const ServiceVersionType& other) const
    {
        return (mMajor == other.mMajor) && (mMinor == other.mMinor);
    }
    bool operator<(const ServiceVersionType& other) const
    {
        if (mMajor < other.mMajor)
        {
            return true;
        }
        else if (mMajor == other.mMajor)
        {
            return mMinor < other.mMinor;
        }
        
        return false;
    }

    ServiceVersionType& operator=(const ServiceVersionType& other)
    {
        mMajor = other.mMajor;
        mMinor = other.mMinor;
        mVersion = other.mVersion;
        return *this;
    }
    ara::core::StringView ToString() const
    {
        return mVersion;
    }
private:
    ara::core::String mVersion;
    uint8_t mMajor = 0;
    uint8_t mMinor = 0;
};

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

/** The Communication Management shall provide a class InstanceIdentifier. 
 *  It only contains instance information, but does not contain a fully qualified 
 *  name, which would also have service type information
 */
class InstanceIdentifier
{
public:
    InstanceIdentifier() = default;
    explicit InstanceIdentifier(ara::core::StringView value)
        :mId(value)
    {
        /** todo something */
    }

public:
    ara::core::StringView ToString() const { return mId; }
    bool operator==(const InstanceIdentifier& other) const
    {
        return mId == other.mId;
    }

    bool operator<(const InstanceIdentifier& other) const
    {
        return mId < other.mId;
    }

    InstanceIdentifier& operator=(const InstanceIdentifier& other)
    {
        mId = other.mId;
        return *this;
    }

private:
    ara::core::String mId;
};

/** Instance Identifier Container Class */
using InstanceIdentifierContainer = ara::core::Vector<InstanceIdentifier>;


/** Event Receive Handler */
using EventReceiveHandler = std::function<void()>;

/** Subscription State Changed Handler */
using SubscriptionStateChangeHandler = std::function<void(SubscriptionState)>;


/** Sample Allocatee Pointer  */
template <typename T>
using SampleAllocateePtr = std::unique_ptr<T>;

/** for network binding type */
using NetworkBindingType = ara::core::String;

} /** namespace com */
} /** namespace ara */

#endif /** !__ARA_COM_DATA_TYPES_H__ */

